import java.io.FileWriter;
import java.io.PrintWriter;
import org.xml.sax.XMLReader;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import java.util.ArrayList;

public class MapParser extends DefaultHandler {
    boolean isWay = false;
    boolean isOneWay = false;
    boolean isHighway = false;
    boolean firstPass = true;
    static int count = 0;
    int currentCost = 0;
    static PrintWriter out;
    ArrayList <String> way;
    ArrayList <String> AllNodes;
    ArrayList <String> Intersections;
    ArrayList <Integer> costs;
    
    String acceptedTypes[] = {"living_street", "motorway", "motorway_link", "primary", "primary_link",
                                "residential", "trunk", "trunk_link", "secondary", "secondary_link"};
    public MapParser(){
        super();
        
        try{
            out = new PrintWriter(new FileWriter("map.pddl"));
            way = new ArrayList<String>();
            AllNodes = new ArrayList<String>();
            Intersections = new ArrayList<String>();
            costs = new ArrayList<Integer>();
        }
        
        catch(Exception e){
            System.err.println(e.getMessage());
        }
    }
    
    @Override
    public void startElement(String uri, String localName,String qName, Attributes attributes) throws SAXException{    
        //the beginning of a way
        if(localName.equals("way")){
            isWay = true;
        }
        
        //connect the nodes in the way
        else if(localName.equals("nd") && isWay){
            String currentNode = "L" + attributes.getValue(uri, "ref");
            
            if(firstPass)
            {
                if(AllNodes.contains(currentNode))
                {
                    if(!(Intersections.contains(currentNode)))
                        Intersections.add(currentNode);
                }
                
                else
                    AllNodes.add(currentNode);

                return;
            }
            
            else{
                currentCost++;
                
                if(Intersections.contains(currentNode)){
                    way.add(currentNode);
                    costs.add(currentCost);
                    currentCost = 0;
                }
            }
        }
      
        else if(localName.equals("tag") && isWay && !firstPass){
            //check if the way is a oneway
            if(attributes.getValue(uri, "k").equals("oneway") && attributes.getValue(uri, "v").equals("yes")){
                isOneWay = true;
            }
            
            //check if the way is one of the allowed ways (highway as opposed to railway, etc)
            else if(attributes.getValue(uri, "k").equals("highway")){
                String value = attributes.getValue(uri, "v");
                
                for(String accepted:acceptedTypes){
                    if(value.equals(accepted)){
                        isHighway = true;
                        return;
                    }
                } 
            }
        }//end else
    }
    
    @Override
    public void endElement (String uri, String name, String qName){
	if(firstPass) return;

        if((name.equals("way") || qName.equals("way"))){     
            if(isHighway){
                for(int i = 1; i < way.size(); i++){
                    String prevNode = way.get(i-1);
                    String currentNode = way.get(i);

                    if(!prevNode.equals(currentNode)){
                        out.println("(Connected " + prevNode + " " + currentNode + ")");

                        if(!isOneWay){
                            out.println("(Connected " + currentNode + " " + prevNode + ")");
                        }
                    }
                }
            }
            
            isOneWay = false;
            isHighway = false;
            isWay = false;
            currentCost = 0;
            way.clear();
            costs.clear();
        }
    }

    /* Parse a map file and generate Map for Strips domain */
    public static void main(String args[]) throws Exception{
        XMLReader xr = XMLReaderFactory.createXMLReader();
        MapParser handler = new MapParser();
        xr.setContentHandler(handler);
        xr.setErrorHandler(handler);
        
        xr.parse(new InputSource("map.osm"));
	handler.firstPass = false;
	xr.parse(new InputSource("map.osm"));
        out.close();
    }
}
